package cn.wolfcode.crm.shiro;
import cn.wolfcode.crm.domain.Employee;
import cn.wolfcode.crm.domain.Role;

import cn.wolfcode.crm.mapper.EmployeeMapper;
import cn.wolfcode.crm.mapper.PermissionMapper;
import cn.wolfcode.crm.mapper.RoleMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("crmRealm")
public class CrmRealm extends AuthorizingRealm {
    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RoleMapper roleMapper;
    /**
     * 提供认证的信息给 shiro
     * @param
     * @return token 就是用户名
     * @throws AuthenticationException,
     * 该方法的返回值决定了是否会抛出异常,
     * 如果返回 null,用户名错误 UnknownAuthenticationToken 异常
     * 如果返回对象,shiro 就会从对象里面获取真正的密码,结合 token 中的密码去判断
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        // 方式一:强转后获取到 username
        // usernamePasswordToken.getUsername();
        // 方式二使用 token 中自带的方法
        // 令牌中的用户名,肯可能是假的
        String username = token.getPrincipal().toString();
        // 根据 username 去查询数据库是否有数据,如果有就可以获取到 用户对象
        // 从数据中查询出来的对象
        Employee employee = employeeMapper.selectByName(username);
        if (employee != null){
            // 返回的对象必须是包含用户真正的密码.提供给 shiro 判断,要么 return null,要么返回 realm 对象
            return new SimpleAuthenticationInfo(employee,employee.getPassword(),this.getName());
        }
        return null;
    }


    /**
     * 提供授权的信息给 shiro
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 返回的结果代表当前用户主体所拥有的信息,例如:权限,角色
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 获取当前用户 id
        Employee employee = (Employee)SecurityUtils.getSubject().getPrincipal();
        // 如果用户不是管理员,则查询
        if (!employee.isAdmin()) {
            System.out.println("..........查询一次............");
            // 根据用户 id 查询该用户所拥有的角色
            List<Role> roles = roleMapper.selectByRoleId(employee.getId());
            for (Role role : roles) {
               info.addRole(role.getSn());
            }
            // 根据用户 id 查询该用户所拥有的权限
            List<String> permissions = permissionMapper.selectByEmployeeId(employee.getId());
            info.addStringPermissions(permissions);
        }else {
            // 分开添加,允许系统只有单个功能,灵活许多
            info.addRole("ADMIN");
            info.addStringPermission("*:*");
        }
        return info;
    }

}
